
import controlP5.*;

//Instancias de las clases
Cargador car;
Slider slider;
Helper helper;
ControlP5 controlP5;
Explorador explorador;
//Variables
boolean cargado=false;
int estado=0;
int x1=0;
int y1=0;
int etiqueta=-1;
int sliderValue=0;
ArrayList puntos= new ArrayList();
PImage b;
ControlGroup mBox;
ListBox l;
//Variables de estado
boolean msg=false;
boolean elim=false;
boolean modif=false;
boolean creando=false;
boolean mpress = true;
int xmov,ymov;
boolean drag = false;
int resAncho=-1;
int resAlto=-1;
int resRadio=-1;
int nEt = 0;
float imgAncho=0;
float imgAlto=0;
float imgAncho2=0;
float imgAlto2=0;
private float zoom=1;
private float dragX=0;
private float dragY=0;
private float xd=0;
private float yd=0;
private float zm =0;
private float zoomy=1;
private PFont font;
//Mensaje para etsado IDLE
private final String MSGIDLE = "Controls: MOUSE LEFT - Select  MOUSE RIGHT - Drag  MOUSE WEHEEL - Zoom";


Herramienta herActual;
//Fondos
PImage fondoEliminar;
PImage marco;
PImage opciones;

//Botones
controlP5.Button eliminar,modificar;


void setup() {
  //size(1024,768);
  size(screen.width,screen.height-100);
  //Creamos la fuente
  font = loadFont("ComicSansMS-Bold-48.vlw");
  //Cargamos el fondo
  b= loadImage("fondo.png");
  b.resize(screen.width,screen.height-100);

  //Iniciamos los componentes
  slider = new Slider();
  explorador = new Explorador(slider.getAlto());
  helper = new Helper(250,explorador.getAncho(),slider.getAlto());
  helper.setVisible(false);
  helper.setText(MSGIDLE);
  controlP5 = new ControlP5(this);


  //Agregamos los botones
  controlP5.addButton("Load", 0,0,0,80,32);
  controlP5.addButton("Save",0,80,0,80,32);
  eliminar=controlP5.addButton("Delete",0,160,0,80,32);
  modificar=controlP5.addButton("Move",0,240,0,80,32);
  controlP5.addButton("Undelete",0,320,0,80,32);
  eliminar.setSwitch(true);
  modificar.setSwitch(true);

  //Listener de la rueda del raton
  addMouseWheelListener(new java.awt.event.MouseWheelListener() { 
    public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { 
      if(!creando) {
        //Incrementamos el zoom
        float zm=1+evt.getWheelRotation()/10.0;
        imgAncho2*=(zm);
        imgAlto2*=(zm);
        zoom=imgAncho2/imgAncho;
        zoomy=imgAlto2/imgAlto;
      }
    }
  }
  );
}
//Funcion que hace de listener del teclado
void keyPressed() {
  //Modo borrar
  if(key=='d') {
    elim=true;
    helper.setText("DELETE MODE: Click any label or press DELETE key to remove it");
  }
  //Modo mover
  if(key=='m') {
    modif=true;
    helper.setText("MOVE MODE: use UP,DOWN,LEFT and RIGHT to move the red label");
  }
  if(key==CODED) {
    //Teclas de movimiento
    if(keyCode==UP) {
      Etiqueta e2 = car.getEtiquetaModif();
      if(e2!=null)
        e2.mover(0,-1);
    }
    if(keyCode==DOWN) {
      Etiqueta e2 = car.getEtiquetaModif();
      if(e2!=null)
        e2.mover(0,1);
    }
    if(keyCode==LEFT) {
      Etiqueta e2 = car.getEtiquetaModif();
      if(e2!=null)
        e2.mover(-1,0);
    }
    if(keyCode==RIGHT) {
      Etiqueta e2 = car.getEtiquetaModif();
      if(e2!=null)
        e2.mover(1,0);
    }
  }
  //Eliminar etiqueta
  if(key==(DELETE)) {
    boolean etBol;
    if(cargado && elim ) {
      //Eliminamos la etiqueta
      etBol = car.borrarEtiqueta(slider.getNumImagenActual());
    }
    else {
      etBol=false;
    }
  }
}
//Listener de dejar ir una tecla
void keyReleased() {
  //Salir del modo borrar
  if(key=='d') {
    elim=false;
    helper.setText(MSGIDLE);
  } 
  //Salir del modo mover
  if(key=='m') {
    modif = false;
    helper.setText(MSGIDLE);
  }
}
//Gestor del boton Undelete que recupera una etiqueta borrada
void Undelete() {
  car.deshacer(slider.getNumImagenActual());
}

//Funcion que dibuja toda la GUI
public void draw() {
  stroke(255);
  background(b);


  //Si hemos cargado imagenes
  if(cargado) {
    //Cojemos la imagen actual
    PImage img = slider.getImagenActual();
    //Seteamos el ancho y el alto sin perder proporciones
    if(imgAncho2==0) {
      if(img.width > width -explorador.getAncho()) {
        this.imgAncho2=img.width/2;
        this.imgAlto2=img.height*(imgAncho2) / img.width;
      }
      if(imgAlto2 > width-slider.getAlto()) {
        float al=imgAlto2;
        this.imgAlto2= imgAlto2/2;
        this.imgAncho2 = imgAncho2*(imgAlto2) / al;
      }
      if(this.imgAncho==0){
       this.imgAncho2=img.width;
      this.imgAlto2=img.height; 
      }
      this.imgAncho=imgAncho2;
      this.imgAlto=imgAlto2;
    }
    //Dibujamos la imagen teniendo en cuenta los parametros DRAG y ZOOM
    image(slider.getImagenActual(),(width-imgAncho2)/2 + dragX,(height-imgAlto2)/2 +dragY,imgAncho2,imgAlto2);
    // Si estamos en el modo eliminar o modificar marcamos en rojo la etiqueta
    // mas cercana al cursor
    if((elim ==true ||modif ==true)&& (mouseX>320 || mouseY>80) && !drag) {
      car.dibujaretiquetas(slider.getNumImagenActual(),(int)imgAncho2,(int)imgAlto2,true,zoom,zoomy,dragX,dragY);
    }
    else {
      car.dibujaretiquetas(slider.getNumImagenActual(),(int)imgAncho2,(int)imgAlto2,false,zoom,zoomy,dragX,dragY);
    }
    //Si hemos cargado imagenes y estamos en el modo modificar seteamos la etiqueta
    // mas cercana al cursor
    if(cargado && modif && !drag) {
      car.setEtMin();
    }
    
    //Mostramos los demas componentes
    slider.display();
    explorador.display();
    helper.display();
    //Si hemos selecionado una herramienta, mostramos el estado de la etiqueta
    // en caso de que la estemos dibujando
    if(herActual!=null ) {
      herActual.displayEstado((int)imgAncho2,(int)imgAlto2,zoom,zoomy,dragX,dragY);
      explorador.drawActive();
    }
  }
  // Si no hemos cargado, mostramos un mensaje con instrucciones
  if(!cargado) {
    //Seleccionamos la fuente a utilizar
    textFont(font,28);
    fill(255);
    String s = "Click LOAD and select a folder with images";
    text(s,width/2-textWidth(s)/2,height/2);
  }
}
//Funcion que se activa al presionar el boton LOAD, carga las imagenes de un directorio
public void Load(int valor) {
  //Comprovamos que no estemos creando ninguna etiqueta
  if(!creando) {
    imgAncho2=0;
    imgAlto2=0 ;
    herActual=null;
    //Mostramos el dialogo de seleccionar el directorio
    String folderPath = selectFolder();
    if (folderPath == null) {
      // Si no seleccionamos ningun directorio
      println("No folder was selected...");
    } 
    else {
      //Si seleccionamos un directorio, cargamos las fotos que estan dentro de el
      car = new Cargador(folderPath+"\\");
      car.cargar(this,explorador);
      
      //Volcamos las imagenes en el slider
      slider.cargar(car.getImagenes());
      cargado=true;
      //Creamos el slider que movera el explorador de imagenes
      crearMenus();
      slider.setNumImagenActual(0);
      slider.actualizar();
    }
  }
}
//Funcion que actualiza el slider de imagenes cuando soltamos el boton del mouse
public void mouseReleased() {
  slider.moverSlider(sliderValue);
  if(modif){
  Etiqueta e2 = car.getEtiquetaModif();
      if(e2!=null)
        e2.mover((int)(mouseX-xd),(int)(mouseY-yd));
 }
drag=false; 
}
//Funcion que se activa al presionar un boton del raton
public void mousePressed() {
  //Adquirimos las posiciones actuales del mouse
  xd=mouseX;
  yd=mouseY;
  boolean bol;
  //si no estamos creando ninguna etiqueta miramos si hemos pulsado el slider
  if(!creando) {
    bol = slider.mousePressed();
  }
  else {
    bol=false;
  }
  // Si lo hemos pulsado, reseteamos la etiqueta minima
  if(bol){
    car.resetMinima();
    car.reiniciarDeshacer();
    imgAncho2=0;
    imgAlto2=0 ;
  }
  boolean etBol;
  // Si no estamos creando y estamos eliminando y el raton esta dentro de la fotografia
  // eliminamos la etiqueta que hemos presionado
  if(!creando&&cargado && elim && mouseX >( (width/2)-imgAncho2/2 )&& mouseX < ((width/2)+imgAncho2/2) && mouseY > ((height/2)-imgAlto2/2 )&& mouseY < ((height/2)+imgAlto2/2)) {
    etBol = car.borrarEtiqueta(slider.getNumImagenActual());
  }
  else {
    etBol=false;
  }
  //Si no estamos modificando ni eliminando y hemos cargado imagenes, creamos una etiqueta
  if(!bol && !etBol && cargado && !elim && explorador.mousePressed() && !modif && !creando) {
   if(herActual!=null){
    herActual.setActiva(false);}
    herActual = explorador.getHerramienta(true);
    if(herActual!=null)
      helper.setText(herActual.getTextoHelper2());
      
  }
  //Creamos la etiqueta
  else if(herActual!=null && !bol && !etBol && cargado && !elim && !modif && mouseX >( (width/2)-imgAncho2/2 +dragX )&& mouseX < ((width/2)+imgAncho2/2 +dragX) && mouseY > ((height/2)-imgAlto2/2 +dragY)&& mouseY < ((height/2)+imgAlto2/2) +dragY && mouseY < height-110 && mouseY > 30) {
    //llamamos al metodo que actualiza el estado de la creacion de etiquetas
    // si devuelve false quiere decir que ha acavado de crear la etiqueta
    boolean crtmp=herActual.mousePressed((int)imgAncho2,(int)imgAlto2,zoom,zoomy,dragX,dragY);

    if(!crtmp && !creando ) {
      creando=true;
      //inhibimos los botones
      eliminar.setSwitch(false);
      modificar.setSwitch(false);
      creando=!crtmp;
    }
    else if(crtmp ) {
      creando=true;
      //volvemos a habilitar los botones
      eliminar.setSwitch(true);
      modificar.setSwitch(true);
      elim=false;
      modif=false;
      eliminar.setOff();
      modificar.setOff();
      modificar.update();
      eliminar.update();
      creando =false;
      //Agregamos la etiqueta a la coleccion
      car.agregarEtiqueta(slider.getNumImagenActual(),herActual.getLastEtiqueta());
    }
  }
}

//Funcion que se activa al presionar el boton DELETE
public void Delete() {
  
  if(!creando) {
    elim=!elim;
    //Si entramos en el estado eliminar, mostramos el texto de ayuda e inhibimos el
    //boton de modificar
    if(elim) {
      explorador.resetHerActual();
      helper.setText("DELETE MODE: Click any label or press DELETE key to remove it");
      if(modificar.booleanValue()) {
        modificar.setOff();
      }
      modif=false;
      herActual=null;
    }
    else {
      if(herActual!=null) {
        helper.setText(herActual.getTextoHelper2());
        
      }
      else {
        helper.setText(MSGIDLE);
      }
    }
  }
  
}
//Funcion que se activa al presionar el boton MOVE
public void Move() {
  if(!creando) {
    modif=!modif;
    //Si entramos en el estado de mover, mostramos el mensaje de ayuda y
    //inhibimos el boton de eliminar.
    if(modif) {
      explorador.resetHerActual();
      helper.setText("MOVE MODE: use UP,DOWN,LEFT and RIGHT to move the red label");
      if(eliminar.booleanValue()) {
        eliminar.setOff();
      }
      elim=false;
      herActual=null;
    }
    else {
      car.resetMinima();
      if(herActual!=null) {
        helper.setText(herActual.getTextoHelper2());
      }
      else {
        helper.setText(MSGIDLE);
      }
    }
  }
  
}
//Funcion que se activa al presionar el boton SAVE
public void Save() {
  if(!creando)
    car.guardarEtiquetas();
}
//Funcion que crea el slider para mover el explorador de imagenes
public void crearMenus() {
  controlP5.addSlider("sliderValue",0,car.getNImagenes(),0,0,height-10,width,10);
}
//Funcion que se activa al mover el mouse
void mouseMoved() {
  //Mostramos el helper flotante de la herramienta que toca
  if( explorador.mousePressed()) {
    Herramienta her =explorador.getHerramienta(false);
    if(her!=null) {
      helper.setTextVar(her.getTextoHelper1());
      helper.setVisible(true);
    }
    else {
      helper.setVisible(false);
    }
  }
  else {
    helper.setVisible(false);
  }
}
//Funcion que se activa al presionar y arrastrar el mouse
void mouseDragged() {
  drag=true;
  if(mouseButton == RIGHT) {
    //Aplicamos el efecto DRAG
    dragX+= (mouseX-xd )/100;
    dragY+=(mouseY-yd)/100;
  }
  if(modif){
  Etiqueta e2 = car.getEtiquetaModif();
      if(e2!=null)
        e2.mover((int)(mouseX-xd),(int)(mouseY-yd));
        xd=mouseX;
        yd=mouseY;
 } 
}


